
"""
    pycoopiler - a compiler developed for PCS2056 course (Compilers) at Poli-USP
    Copyright (C) 2008 Andre Felipe Santos    
    Copyright (C) 2008 Rodrigo Rodrigues da Silva

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
"""

from pycoopiler.token import *
from pycoopiler.enum import enum
from pycoopiler.submaquina import submaquina
from pycoopiler.maq_largs import maq_largs
from pycoopiler.maq_decls import maq_decls
from pycoopiler.maq_cmds import maq_cmds
from pycoopiler.maq_ref import maq_ref
import logging

class maq_program(submaquina):
    
    states = enum("  _0_INT_OU_VOID \
                     _1_ID \
                     _4_LARGS \
                     _5_OPEN_CB \
                     _6_DECLS \
                     _7_CMDS \
                     _8_RET \
                     _9_REF \
                     _13_SEMICOLON \
                     _14_CLOSE_CB \
                     _18_INT_OU_VOID")
    
    def __init__(self, _tkzr):
        self.tkzr = _tkzr 
        self.state = self.states._0_INT_OU_VOID
        self.name = "PROGRAM"
        self.log_chamada(self.name)
        self.current = self.tkzr.current

    def analyze(self):
                
        while not (self.state == self.states._18_INT_OU_VOID and \
                   not (self.current.type == self.current.types.INT or self.current.type == self.current.types.VOID)):            
            
            self.log_state()
            
            if self.state == self.states._0_INT_OU_VOID: 
                if self.current.type == self.current.types.INT:
                    self.state = self.states._1_ID   
                elif self.current.type == self.current.types.VOID:
                    self.state = self.states._1_ID           
                else: raise Exception ("Erro Sintatico! Esperando INT ou VOID")
                self.consume()  
            
            elif self.state == self.states._1_ID:
                if self.current.type == self.current.types.ID:
                    self.state = self.states._4_LARGS
                else: raise Exception ("Erro Sintatico! Esperando ID")
                self.consume()
                
            elif self.state == self.states._4_LARGS:
                m = maq_largs(self.tkzr)
                try: m.analyze()
                except: raise
                self.current = self.tkzr.current
                self.state = self.states._5_OPEN_CB
            
            elif self.state == self.states._5_OPEN_CB:
                if self.current.type == self.current.types.OPEN_CB:
                    self.state = self.states._6_DECLS              
                else: raise Exception ("Erro Sintatico! Esperando OPEN_CB")
                self.consume()
                
            elif self.state == self.states._6_DECLS:
                m = maq_decls(self.tkzr)
                try: m.analyze()
                except: raise
                self.current = self.tkzr.current
                self.state = self.states._7_CMDS
                
            elif self.state == self.states._7_CMDS:
                m = maq_cmds(self.tkzr)
                try: m.analyze()
                except: raise
                self.current = self.tkzr.current
                self.state = self.states._8_RET
            
            elif self.state == self.states._8_RET:
                if self.current.type == self.current.types.RETURN:
                    self.state = self.states._9_REF              
                else: raise Exception ("Erro Sintatico! Esperando RET")
                self.consume()
                
            elif self.state == self.states._9_REF:
                m = maq_ref(self.tkzr)
                try: m.analyze()
                except: raise
                self.current = self.tkzr.current
                self.state = self.states._13_SEMICOLON
                
            elif self.state == self.states._13_SEMICOLON:
                if self.current.type == self.current.types.SEMICOLON:
                    self.state = self.states._14_CLOSE_CB             
                else: raise Exception ("Erro Sintatico! Esperando CLOSE_CB")
                self.consume()
                
            elif self.state == self.states._14_CLOSE_CB:
                if self.current.type == self.current.types.CLOSE_CB:
                    self.state = self.states._18_INT_OU_VOID              
                else: raise Exception ("Erro Sintatico! Esperando SEMICOLON")
                self.consume()
            
            elif self.state == self.states._18_INT_OU_VOID: 
                if self.current.type == self.current.types.INT:
                    self.state = self.states._1_ID   
                elif self.current.type == self.current.types.VOID:
                    self.state = self.states._1_ID           
                else: raise Exception ("Erro Sintatico! Esperando INT ou VOID")
                self.consume()  
            
            else: raise Exception("ERRO: Estado invalido: " + self.state)
        self.log_retorno(self.name)